package cn.study.concurrenttools.stampedlock;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.StampedLock;

/**
 * @Author     ：跟大佳一起学
 * @Description：StampedLock 简单示例
 */
public class StampedLockTest {
    private static final StampedLock stampedLock = new StampedLock();

    private static final ReadWriteLock lock = new ReentrantReadWriteLock();

    private static int value;

    public static void main(String[] args) {
        // 1、先读2次
        new Thread(()->{
            getValueByStamped();
        }).start();
        new Thread(()->{
            getValueByStamped();
        }).start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 2、在写2次
        new Thread(()->{
            writeValue(2);
            writeValue(2);
        }).start();
        new Thread(()->{
            writeValue(3);
        }).start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 3、在读一次
        getValueByStamped();
    }

    public static int getValueByStamped() {
        long stamp = stampedLock.tryOptimisticRead();
        int result = value;
        if (!stampedLock.validate(stamp)) {
            stamp = stampedLock.readLock();
            try {
                result = value;
            } finally {
                stampedLock.unlockRead(stamp);
            }
        }
        System.out.println("执行读："+result);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return result;
    }


    public static void writeValue(int v) {
        long stamp = stampedLock.writeLock();
        try {
//            long stamp1 = stampedLock.writeLock();

            value = v;
            System.out.println("执行写:"+v);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        } finally {
            stampedLock.unlockWrite(stamp);
        }
    }

}